package mashibing.class11;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;

/**
 * 二叉树层最大节点数
 *
 * @author yujiafan
 * @version 1.0.0
 * @create 2023-05-17
 */
public class Class11_5_TreeMaxWidth {

    public static class Node {
        public int value;
        public Node left;
        public Node right;

        public Node(int data) {
            this.value = data;
        }
    }

    public static int maxWidthUseMap(Node root) {
        if (root == null) {
            return 0;
        }
        Queue<Node> queue = new LinkedList<>();
        queue.add(root);
        // map记录节点层级数
        Map<Node, Integer> map = new HashMap<>();
        map.put(root, 1);
        // 当前层
        int curLevel = 1;
        // 层数量
        int curLevelWidth = 0;
        int max = 0;
        while (!queue.isEmpty()) {
            Node poll = queue.poll();
            Integer curNodeLevel = map.get(poll);
            if (poll.left != null) {
                queue.add(poll.left);
                map.put(poll.left, curNodeLevel + 1);
            }
            if (poll.right != null) {
                queue.add(poll.right);
                map.put(poll.right, curNodeLevel + 1);
            }
            if(curLevel == curNodeLevel){
                curLevelWidth++;
            } else {
                curLevel++;
                max = Math.max(max,curLevelWidth);
                curLevelWidth = 1;
            }
        }
        return Math.max(max,curLevelWidth);
    }

    public static int maxWidthNoMap(Node root) {
        if (root == null) {
            return 0;
        }
        Queue<Node> queue = new LinkedList<>();
        queue.add(root);
        Node curEndNode = root;
        Node nextEndNode = null;
        int curLevelWidth = 0;
        int max = 0;
        while (!queue.isEmpty()){
            Node poll = queue.poll();
            curLevelWidth++;
            if(poll.left != null){
                queue.add(poll.left);
                nextEndNode = poll.left;
            }
            if(poll.right != null){
                queue.add(poll.right);
                nextEndNode = poll.right;
            }
            if(poll == curEndNode){
                max = Math.max(max,curLevelWidth);
                curLevelWidth = 0;
                curEndNode = nextEndNode;
            }
        }
        return max;
    }


    public static void main(String[] args) {
        int maxLevel = 10;
        int maxValue = 100;
        int testTimes = 1000000;
        for (int i = 0; i < testTimes; i++) {
            Node head = generateRandomBST(maxLevel, maxValue);
            if (maxWidthUseMap(head) != maxWidthNoMap(head)) {
                System.out.println("Oops!");
            }
        }
        System.out.println("finish!");

    }

    // for test
    public static Node generateRandomBST(int maxLevel, int maxValue) {
        return generate(1, maxLevel, maxValue);
    }

    // for test
    public static Node generate(int level, int maxLevel, int maxValue) {
        if (level > maxLevel || Math.random() < 0.5) {
            return null;
        }
        Node head = new Node((int) (Math.random() * maxValue));
        head.left = generate(level + 1, maxLevel, maxValue);
        head.right = generate(level + 1, maxLevel, maxValue);
        return head;
    }
}
